package com.lyl.dangdang.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lyl.dangdang.mapper.*;
import com.lyl.dangdang.pojo.Result;
import com.lyl.dangdang.pojo.dto.LoginDto;
import com.lyl.dangdang.pojo.dto.PayDateDto;
import com.lyl.dangdang.pojo.dto.RegisterDto;
import com.lyl.dangdang.pojo.po.*;
import com.lyl.dangdang.pojo.vo.CartBooksVo;
import com.lyl.dangdang.pojo.vo.LoginVo;
import com.lyl.dangdang.pojo.vo.PayVo;
import com.lyl.dangdang.service.EmailService;
import com.lyl.dangdang.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyl.dangdang.utils.JwtUtil;
import com.lyl.dangdang.utils.Md5Util;
import com.lyl.dangdang.utils.ThreadLocalUtil;
import com.lyl.dangdang.utils.VerifyCodeUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liyunlong
 * @since 2024-06-03
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private  UserMapper userMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private LineCaptcha lineCaptcha;

    @Autowired
    private EmailService emailService;

    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private BookMapper bookMapper;

    @Autowired
    private ItemMapper itemMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private PayMapper payMapper;

    public static final String REGISTER_CODE="registerCode:";
    @Override
    public Result login(LoginDto user) {
        String email = user.getEmail();
        String password = user.getPassword();
        if (email==null|| password==null){
            return Result.error("用户名或密码不能为空！！");
        }
       User logUser= userMapper.findByEmail(email);
        if (logUser==null){
            return Result.error("该用户尚未注册");
        }
        Integer userId = logUser.getUserId();
        String salt = logUser.getSalt();
        password=salt+password;
        String md5SaltPassword = Md5Util.getMD5String(password);
        if (!md5SaltPassword.equals(logUser.getPassword())){
            return Result.error("输入密码有误！");
        }
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", logUser.getUserId());
        claims.put("username", logUser.getEmail());
        String token = JwtUtil.createJWT("liyunlong", 60000*30, claims);
        redisTemplate.opsForValue().set("token:"+logUser.getUserId(),token,60000*30, TimeUnit.MINUTES);
        ThreadLocalUtil.addCurrentUser(userId);

        Integer currentUser = ThreadLocalUtil.getCurrentUser();

        System.out.println(currentUser);
        LoginVo loginVo = new LoginVo();
        loginVo.setUserId(logUser.getUserId());
        loginVo.setNickname(logUser.getNickname());
        loginVo.setEmail(logUser.getEmail());
        loginVo.setToken(token);
        return Result.success(loginVo);
    }

    @Override
    @Transactional
    public Result register(RegisterDto registerDto) {
        String email = registerDto.getEmail();
        String password = registerDto.getPassword();
        String code = registerDto.getCode();
        if (!code.equals(lineCaptcha.getCode())) {
            return Result.error("验证码输入有误！");
        }
        if (email == null || password == null) {
            return Result.error("用户名密码为空");
        }
        User byEmail = userMapper.findByEmail(email);
        if (byEmail != null) {
            return Result.error("用户已存在");
        }
            String registerCode = VerifyCodeUtils.generateNum(6);
            redisTemplate.opsForValue().set(REGISTER_CODE + email, registerCode, 2, TimeUnit.MINUTES);
            emailService.sendSimpleMail(email, "欢迎注册", "欢迎注册我的当当网，您的验证码是：" + registerCode+"有效期为2分钟，请及时验证！");
            return Result.success();
    }
    @Override
    public Result getRegisterInfo(Long id) {
        User user = userMapper.findById(id);
        RegisterDto registerDto = new RegisterDto();
        registerDto.setNickname(user.getNickname());
        registerDto.setEmail(user.getEmail());
        return Result.success(registerDto);
    }

    @Override
    public void getCode(HttpServletResponse response) {
        // 随机生成 4 位验证码
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 5);
        // 定义图片的显示大小
        lineCaptcha = CaptchaUtil.createLineCaptcha(100, 30);
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "No-cache");
        try {
            lineCaptcha.setGenerator(randomGenerator);
            lineCaptcha.write(response.getOutputStream());
            log.info("生成的验证码:{}", lineCaptcha.getCode());
            response.getOutputStream().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public Result verifyRegisterCode(RegisterDto registerCodeDto) {
        String registerCode = registerCodeDto.getCode();
        String email = registerCodeDto.getEmail();
        String password = registerCodeDto.getPassword();
        String redisRegisterCode = redisTemplate.opsForValue().get(REGISTER_CODE + email);
        if (redisRegisterCode == null) {
            return Result.error("验证码已过期，请从新注册");
        }
        if (!registerCode.equals(redisRegisterCode)){
            return Result.error("验证码输入有误");
        }
        String salt = UUID.randomUUID().toString();
        password = salt + password;
        String md5Password = Md5Util.getMD5String(password);
        User user = new User();
        user.setEmail(email);
        user.setNickname(registerCodeDto.getNickname());
        user.setPassword(md5Password);
        user.setSalt(salt);
        user.setCode(registerCode);
        int insert = userMapper.insert(user);
        if (insert > 0) {
            redisTemplate.delete(REGISTER_CODE + email);
            return Result.success(user);
        }
        return Result.error("注册失败");
    }

    @Override
    public Result getUserAddress() {
        Integer currentUser = ThreadLocalUtil.getCurrentUser();
        LambdaQueryWrapper<Address> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Address::getUserId, currentUser);
        List<Address> addressList = addressMapper.selectList(queryWrapper);
        return Result.success(addressList);
    }

    @Override
    public Result getUserCartsBook() {
        Integer currentUser = ThreadLocalUtil.getCurrentUser();
        Set<CartBooksVo> cartBooks = new HashSet<>();
        // LambdaQueryWrapper<Item> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // lambdaQueryWrapper.eq(Item::getUserId, currentUser);
        // lambdaQueryWrapper.eq(Item::getOrderId, null);
        List<Item> items = itemMapper.selectByUserIdAndNullOderId(currentUser);
        items.forEach(item -> {
            Book book = bookMapper.findById(item.getBookId());
            CartBooksVo cartBooksVo = new CartBooksVo();
            cartBooksVo.setBookId(book.getBookId());
            cartBooksVo.setBookName(book.getBookName());
            cartBooksVo.setPrice(book.getPrice());
            cartBooksVo.setCount(item.getCount());
            cartBooksVo.setDprice(book.getDprice());
            cartBooksVo.setCover(book.getCover());
            cartBooks.add(cartBooksVo);
        });
        return Result.success(cartBooks);
    }

    @Override
    @Transactional
    public Result payOrder(PayDateDto payDateDto) {
        Integer currentUser = ThreadLocalUtil.getCurrentUser();
        // 根据用户id 去查询 购物车中的 商品数据 包含 商品的id  和数量 此时的 购物车中的 orderid 为空
        List<Item> items = itemMapper.selectByUserIdAndNullOderId(currentUser);
        // 遍历item 找对应的商品
        items.forEach(item -> {
            //   更新book 中的  销量
            Integer bookId = item.getBookId();
            Integer count = item.getCount();
            bookMapper.updateByBookIdIncreaseSale(count, bookId);
        });
        // 获取地址信息
        Integer addressId = payDateDto.getAddressId();
        Address address = addressMapper.selectByUserIdAndAddressId(addressId, currentUser);
        // 准备生成订单
        Order order = new Order();
        BeanUtils.copyProperties(address, order);
        order.setUserId(currentUser);
        order.setStatus(0);
        order.setCreateDate(LocalDateTime.now());
        Integer dpriceCountSum = payDateDto.getDpriceCountSum();
        order.setTotal(Double.valueOf(dpriceCountSum));
        Integer insert = orderMapper.insert(order);
        Long orderId;
        if (insert > 0) {
            //     订单生成成功
            orderId = order.getOrderId();
            items.forEach(item -> {
                // Item item1 = new Item();
                Integer itemId = item.getItemId();
                itemMapper.updateOrder(itemId, orderId);
            });
            Pay pay = new Pay();
            pay.setUserId(currentUser);
            pay.setOrderId(orderId);
            pay.setAmount(BigDecimal.valueOf(dpriceCountSum));
            pay.setPayMethod(1);
            pay.setPayStatus(20);
            pay.setCreateTime(LocalDateTime.now());
            int insert1 = payMapper.insert(pay);
            if (insert1 > 0) {
                order.setStatus(1);
                orderMapper.updateById(order);
            }
        } else {
            orderId = null;
        }
        PayVo payVo = new PayVo();
        payVo.setTotal(Double.valueOf(dpriceCountSum));
        payVo.setOrderId(orderId);
        return Result.success(payVo);
    }
}
